home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / lisp / kcl / kcl.lha / uts / ild.c next >
C/C++ Source or Header  |  1987-05-08  |  8KB  |  350 lines

  1. /*
  2.     ild: incremental linker/loader on System V
  3.  
  4.                 (C) Masami Hagiya, 1986
  5.               UTS version       (C) Akiumi Hasegawa, 1987
  6.  
  7.     Usage:
  8.         % ild loading_object start_address \
  9.               loaded_object output_file
  10.     
  11.     The start address is in decimal.
  12.  
  13.     How to Create:
  14.  
  15.     To compile this file (ild.c) and make ild, do the following.
  16.  
  17.         % cc -o ild ild.c -lld
  18.  
  19.     
  20.     Problem:
  21.     This program only supports the simplest linear search for symbols.
  22.  
  23.         This program is modified for UTS system.
  24.  
  25. */
  26.  
  27. #include <stdio.h>
  28. #include <filehdr.h>
  29. #include <aouthdr.h>
  30. #include <scnhdr.h>
  31. #include <reloc.h>
  32. #include <syms.h>
  33. #include <storclass.h>
  34. #include <ldfcn.h>
  35.  
  36. struct filehdr my_header;
  37. struct syment *my_symbol_table;
  38. char *my_string_table;
  39.  
  40. struct filehdr header;
  41. struct aouthdr opt_header;
  42. struct scnhdr section[9];
  43. char *text;
  44. struct syment *symbol_table;
  45. char *string_table;
  46.  
  47. char *start_address;
  48.  
  49. struct reloc relocation_info;
  50.  
  51. main(argc, argv)
  52. int argc;
  53. char *argv[];
  54. {
  55.     if (argc < 5) {
  56.         fprintf(stderr, "Arg count.\n");
  57.         exit(1);
  58.     }
  59.  
  60. #ifdef DEBUG
  61.         printf("ild %s %s %s %s\n", argv[1], argv[2], argv[3], argv[4]);
  62.     fflush(stdout);
  63. #endif
  64.  
  65.         get_myself(argv[1]);
  66.     start_address = (char *)atoi(argv[2]);
  67.  
  68. #ifdef DEBUG
  69.         printf("start address= %x\n",(int)start_address);fflush(stdout);
  70. #endif
  71.  
  72.     fasload(argv[3], argv[4]);
  73.     exit(0);
  74. }
  75.  
  76. get_myself(filename)
  77. char *filename;
  78. {
  79.     int i;
  80.     LDFILE *ldptr;
  81.     extern char *malloc();
  82.     ldptr = ldopen(filename, NULL);
  83.     if (ldptr == NULL) {
  84.         fprintf(stderr, "Can't open %s\n", filename);
  85.         exit(1);
  86.     }
  87.  
  88.     ldfhread(ldptr, &my_header);
  89.  
  90.     ldtbseek(ldptr);
  91.     my_symbol_table
  92.     = (struct syment *)malloc(sizeof(struct syment) * my_header.f_nsyms);
  93.  
  94.     /*
  95.     sizeof(struct syment) and SYMESZ are not always the same.
  96.     */
  97.  
  98.         if(my_symbol_table == NULL){
  99.                 fprintf(stderr,"Can't allocate memory for my_symbol_table\n");
  100.                 exit(1);
  101.         }
  102.     for (i = 0;  i < my_header.f_nsyms;  i++)
  103.         FREAD(&my_symbol_table[i], SYMESZ, 1, ldptr);
  104.  
  105.     /*
  106.     If the string table is not empty,
  107.     its length is stored after the symbol table,
  108.     This is described in the manual.
  109.         (see UTS Support Tools Guide V10L20)
  110.     */
  111.  
  112.     if (FREAD(&i, 4, 1, ldptr) > 0)    {
  113.         my_string_table = malloc(i);
  114.         FSEEK(ldptr, -4, 1);
  115.         FREAD(my_string_table, 1, i, ldptr);
  116.     }
  117.  
  118.     ldclose(ldptr);
  119. }
  120.  
  121. fasload(filename, outputfilename)
  122. char *filename, *outputfilename;
  123. {
  124.     register struct syment *sym, *end;
  125.     int i, n;
  126.     LDFILE *ldptr;
  127.     FILE *fp;
  128.  
  129.     extern char *malloc();
  130.  
  131.     ldptr = ldopen(filename, "r");
  132.     if (ldptr == NULL) {
  133.         fprintf(stderr, "Can't open %s\n", filename);
  134.         exit(1);
  135.     }
  136.  
  137.     ldfhread(ldptr, &header);
  138.  
  139.         FREAD(&opt_header,sizeof(struct aouthdr),1,ldptr);
  140.  
  141.     if (header.f_nscns < 3 || header.f_nscns > 8) {
  142.         fprintf(stderr, "Illegal number of sections.\n");
  143.         exit(1);
  144.     }
  145.  
  146.     for (i = 1;  i <= header.f_nscns;  i++)
  147.         ldshread(ldptr, i, §ion[i]);
  148.  
  149.     if (strcmp(section[1].s_name, ".text") != 0) {
  150.         fprintf(stderr, ".text not found.\n");
  151.         exit(1);
  152.     }
  153.     if (strcmp(section[2].s_name, ".data") != 0) {
  154.         fprintf(stderr, ".data not found.\n");
  155.         exit(1);
  156.     }
  157.     /*
  158.     The bss segment need not exist.
  159.     */
  160.     /*
  161.     if (strcmp(section[3].s_name, ".bss") != 0) {
  162.         fprintf(stderr, ".bss not found.\n");
  163.         exit(1);
  164.     }
  165.     */
  166.  
  167.     if (section[1].s_size > 0 &&
  168.         section[1].s_scnptr !=
  169.         sizeof(struct filehdr) + sizeof(struct aouthdr) +
  170.         header.f_nscns*sizeof(struct scnhdr)) {
  171.         fprintf(stderr, "Contradictory text start.\n");
  172.         exit(1);
  173.     }
  174.     if (section[1].s_size > 0 && section[2].s_size > 0 &&
  175.         section[1].s_scnptr + section[1].s_size !=
  176.         section[2].s_scnptr) {
  177.         fprintf(stderr, "Contradictory data start.\n");
  178.         exit(1);
  179.     }
  180.  
  181.     text = malloc(section[1].s_size + section[2].s_size);
  182.  
  183.     FSEEK(ldptr, section[1].s_scnptr, 0);
  184.     FREAD(text, 1, section[1].s_size + section[2].s_size, ldptr);
  185.  
  186.     ldtbseek(ldptr);
  187.     symbol_table
  188.     = (struct syment *)malloc(sizeof(struct syment) * header.f_nsyms);
  189.     /*
  190.     sizeof(struct syment) and SYMESZ are not always the same.
  191.     */
  192.     for (i = 0;  i < header.f_nsyms;  i++)
  193.         FREAD(&symbol_table[i], SYMESZ, 1, ldptr);
  194.     /*
  195.     If the string table is not empty,
  196.     its length is stored after the symbol table,
  197.     This is described in the manual.
  198.         (see UTS Support Tools Guide V10L20)
  199.     */
  200.  
  201.     if (FREAD(&i, 4, 1, ldptr) > 0)    {
  202.         string_table = malloc(i);
  203.         FSEEK(ldptr, -4, 1);
  204.         FREAD(string_table, 1, i, ldptr);
  205.     }
  206.  
  207.     end = symbol_table + header.f_nsyms;
  208.     for (sym = symbol_table; sym < end; sym++) {
  209.         switch (sym->n_scnum)    {
  210.                 /* in UTS, relocatable address is the offset in the
  211.                    section, in which it defined.
  212.                    Thus "sym->n_value" for each section should be 
  213.                    the the top address of the section. 
  214.                    in case of ".data" section, s_vaddr is equal to 
  215.                    s_size. However, ".bss" section, s_vaddr <> 
  216.                    textsize+datasize. I cannot understand why. But 
  217.                    this code works well.
  218.                 */
  219.         case 1:
  220.                        /* .text */
  221.                        sym->n_value = (int)start_address; break;
  222.                 case 2:
  223.                        /* .data */
  224.                        sym->n_value = (int)start_address + section[1].s_size;
  225.                        break;
  226.                 case 3:
  227.                        /* .bss */
  228.                        sym->n_value = (int)start_address + section[1].s_size 
  229.                                       + section[2].s_size;
  230.                        break;
  231.  
  232.         case N_UNDEF:
  233.             search_symbol(sym);
  234.             break;
  235.         default:
  236.             /*
  237.             Does nothing. Is it OK?
  238.             */
  239.             break;
  240.         }
  241.         sym += sym->n_numaux;
  242.     }
  243.  
  244.     if(ldrseek(ldptr, 1) ==FAILURE){
  245.            fprintf(stderr,"Can't locate relocation table\n");
  246.            exit(1);
  247.          }
  248.         for (i=0; i< section[1].s_nreloc; i++){ 
  249.                 FREAD(&relocation_info,10,1,ldptr);
  250.         relocate();
  251.     }
  252.  
  253.     ldrseek(ldptr, 2);
  254.     for (i = 0; i < section[2].s_nreloc; i++) {
  255.         FREAD(&relocation_info, 10, 1, ldptr);
  256.         relocate();
  257.     }
  258.  
  259.     fp = fopen(outputfilename, "w");
  260.     if (fp == NULL)    {
  261.         fprintf(stderr, "Can't creat %s.\n", outputfilename);
  262.         exit(1);
  263.     }
  264.         fwrite(&header, sizeof(struct filehdr), 1, fp);
  265.         fwrite(&opt_header,sizeof(struct aouthdr),1,fp);
  266.     for (i = 1; i<= header.f_nscns; i++) 
  267.         fwrite(§ion[i], sizeof(struct scnhdr), 1, fp); 
  268.     fwrite(text, 1, section[1].s_size + section[2].s_size, fp);
  269.  
  270.     fclose(fp);
  271.     ldclose(ldptr);
  272. }
  273.  
  274. search_symbol(sym)
  275. register struct syment *sym;
  276. {
  277.     register struct syment *p, *end;
  278.     end = my_symbol_table + my_header.f_nsyms;
  279.     for (p = my_symbol_table; p < end; p++)    {
  280.         /*
  281.         Is the following check enough?
  282.         */
  283.         if (1 <= p->n_scnum && p->n_scnum <= 3 &&
  284.             p->n_sclass == C_EXT &&
  285.             (sym->n_zeroes == 0
  286.             ? (p->n_zeroes == 0 &&
  287.                strcmp(&my_string_table[p->n_offset],
  288.                   &string_table[sym->n_offset]) == 0)
  289.             : (p->n_zeroes != 0 &&
  290.                strncmp(p->n_name, sym->n_name, SYMNMLEN) == 0)))
  291.                 goto FOUND;
  292.         p += p->n_numaux;
  293.     }
  294.  
  295.     sym->n_name[SYMNMLEN] = '\0';
  296.     fprintf(stderr, "%s: undefined symbol.\n",
  297.         (sym->n_zeroes ? sym->n_name : &string_table[sym->n_offset]));
  298.     exit(1);
  299.  
  300. FOUND:
  301.     sym->n_value = p->n_value;
  302. }
  303.  
  304. relocate()
  305. {
  306.     char *where, *p;
  307.     int value;
  308.  
  309.     where = text + relocation_info.r_vaddr;
  310.     if (relocation_info.r_type == R_ABS)
  311.         return;
  312.     /*
  313.     The following code depends on CPU.
  314.         in case of UTS, R_RELLONG is assumed.
  315.     */
  316.     if (relocation_info.r_type != R_RELLONG) {
  317.         fprintf(stderr, "%d: unsupported relocation type.",
  318.             relocation_info.r_type);
  319.         exit(1);
  320.     }
  321.     /*
  322.     Assuming R_RELLONG.
  323.     */
  324.     p = (char *)(&value);
  325.     p[0] = where[0];
  326.     p[1] = where[1];
  327.     p[2] = where[2];
  328.     p[3] = where[3];
  329.  
  330. #ifdef DEBUG
  331.         printf("%s\n",
  332.                (symbol_table[relocation_info.r_symndx].n_zeroes ?
  333.                 symbol_table[relocation_info.r_symndx].n_name :
  334.                 &string_table
  335.                   [symbol_table[relocation_info.r_symndx].n_offset])); 
  336.         printf("value = %x\n",value);fflush(stdout);
  337. #endif
  338.  
  339.         value += symbol_table[relocation_info.r_symndx].n_value;
  340.  
  341. #ifdef DEBUG
  342.         printf("value = %x\n",value);fflush(stdout);
  343. #endif
  344.  
  345.     where[0] = p[0];
  346.     where[1] = p[1];
  347.     where[2] = p[2];
  348.     where[3] = p[3];
  349. }
  350.